package org.epanetgrid.otimizacao.evaluators;

import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.epanetgrid.otimizacao.replicador.ReplicadorOperator;
import org.epanetgrid.otimizacao.searchspace.BulkIndividualEvaluator;
import org.jheuristics.Individual;
import org.jheuristics.ga.FitnessEvaluator;
import org.jheuristics.ga.GAConfig;
import org.jheuristics.ga.GAStatus;
import org.jheuristics.ga.Population;
import org.jheuristics.ga.multiObjective.BulkMultiObjetiveFitnessEvaluator;
import org.jheuristics.ga.multiObjective.DistanceAlgorithm;
import org.jheuristics.util.BitString;


/**
 * Classe que faz a associa��o do indiv�duo com o dataApplication e seta o Fitness (multi objetivo) no indiv�duo.
 * @author vinicius
 *
 */
public class IndividualBulkMultiObjectiveFitnessEvaluator extends BulkMultiObjetiveFitnessEvaluator {
	
	/**
	 * 
	 */
	private static final long serialVersionUID = -5909561111600141245L;
	
	private BulkIndividualEvaluator bulkIndividualEvaluator;

	/**
	 * @param bulkIndividualEvaluator
	 * @param evaluator
	 * @param distanceAlgorithm
	 * @param indexDistance
	 * @param replicador
	 */
	public IndividualBulkMultiObjectiveFitnessEvaluator(BulkIndividualEvaluator bulkIndividualEvaluator, 
			FitnessEvaluator evaluator, DistanceAlgorithm distanceAlgorithm, int indexDistance, ReplicadorOperator replicador) {
		super(evaluator, distanceAlgorithm, indexDistance, replicador);
		setBulkIndividualEvaluator(bulkIndividualEvaluator);
	}

	/* (non-Javadoc)
	 * @see org.jheuristics.ga.multiObjective.BulkMultiObjetiveFitnessEvaluator#evaluatingFitness(org.jheuristics.ga.Population, org.jheuristics.ga.GAStatus, org.jheuristics.ga.GAConfig)
	 */
	protected void evaluatingFitness(Population population, GAStatus status, GAConfig config) {
		if (null != bulkIndividualEvaluator) {
			List individuals = Arrays.asList(population.toIndividualArray());
			
			List result = bulkIndividualEvaluator.evaluate(individuals);
			
			Map<List<BitString>, Individual> mapResult = new HashMap<List<BitString>, Individual>();
			
			for (Object object : result) {
				Individual individual = (Individual) object;
				mapResult.put((List<BitString>) individual.getGens(), individual);
			}

			for (Object object : individuals) {
				Individual individual = (Individual) object;
				Individual indResult = mapResult.get((List<BitString>)individual.getGens());
				if (indResult != null) {
					individual.setDataApplication(indResult.getDataApplication());					
				}
			}
			
//			for (Iterator it1 = individuals.iterator(), it2 = result.iterator(); it1.hasNext() && it2.hasNext(); ) {
//				((Individual) it1.next()).setDataApplication(((Individual) it2.next()).getDataApplication());
//			}
			
		}
		super.evaluatingFitness(population, status, config);
	}

	/**
	 * @return
	 */
	public BulkIndividualEvaluator getBulkIndividualEvaluator() {
		return bulkIndividualEvaluator;
	}

	/**
	 *
	 * @param bulkIndividualEvaluator
	 */
	public void setBulkIndividualEvaluator(BulkIndividualEvaluator bulkIndividualEvaluator) {
		this.bulkIndividualEvaluator = bulkIndividualEvaluator;
	}

}
